﻿using Cms.Core.Infrastructure.Attributes;
using Cms.Core.Infrastructure.Extension;
using Cms.Core.Infrastructure.Filter;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace Cms.Core.Infrastructure.Dependency
{
    /// <summary>
    /// 应用程序服务添加者
    /// </summary>
    public class AppServiceAdder : IAppServiceAdder
    {
        //private TransientDependencyTypeFinder transientDependencyType = null;
        //private ScopedDependencyTypeFinder scopedDependencyTypeFinder = null;
        //private SingletonDependencyTypeFinder singletonDependencyTypeFinder = null;

        //public AppServiceAdder()
        //{
        //    transientDependencyType = new TransientDependencyTypeFinder();
        //    scopedDependencyTypeFinder = new ScopedDependencyTypeFinder();
        //    singletonDependencyTypeFinder = new SingletonDependencyTypeFinder();
        //}

        public IServiceCollection AddServices(IServiceCollection services)
        {
            IDependencyTypeFinder dependencyTypeFinder = new DependencyTypeFinder();
            Type[] dependencyTypes = dependencyTypeFinder.FindAll();

            foreach (Type dependencyType in dependencyTypes.Where(o => !o.IsAbstract || !o.IsInterface))
            {
                AddToServices(services, dependencyType);
            }
            ////添加即时生命周期类型的服务
            //Type[] transientDependencyTypes = transientDependencyType.FindAll();
            //AddTypeWithInterfaces(services, transientDependencyTypes, ServiceLifetime.Transient);

            ////获取或设置 作用域生命周期服务类型查找器
            //Type[] scopedDependencyTypes = scopedDependencyTypeFinder.FindAll();
            //AddTypeWithInterfaces(services, scopedDependencyTypes, ServiceLifetime.Scoped);

            ///// <summary>
            ///// 获取或设置 单例生命周期服务类型查找器
            ///// </summary>
            //Type[] singletonDependencyTypes = singletonDependencyTypeFinder.FindAll();
            //AddTypeWithInterfaces(services, singletonDependencyTypes, ServiceLifetime.Singleton);

            return services;
        }


        /// <summary>
        /// 将服务实现类型注册到服务集合中
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="implementationType">要注册的服务实现类型</param>
        protected virtual void AddToServices(IServiceCollection services, Type implementationType)
        {

            ServiceLifetime? lifetime = GetLifetimeOrNull(implementationType);
            if (lifetime == null)
            {
                return;
            }

            DependencyAttribute dependencyAttribute = implementationType.GetAttribute<DependencyAttribute>();



            Type[] serviceTypes = GetImplementedInterfaces(implementationType);
            //服务数量为0时注册自身
            if (serviceTypes.Length == 0)
            {
                services.TryAdd(new ServiceDescriptor(implementationType, implementationType, lifetime.Value));
                return;
            }

            if (dependencyAttribute?.AddSelf == true)
            {
                services.TryAdd(new ServiceDescriptor(implementationType, implementationType, lifetime.Value));
            }

            //注册服务
            for (int i = 0; i < serviceTypes.Length; i++)
            {
                Type serviceType = serviceTypes[i];
                ServiceDescriptor descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime.Value);
                if (lifetime.Value == ServiceLifetime.Transient)
                {
                    services.TryAddEnumerable(descriptor);
                    continue;
                }

                bool multiple = serviceType.HasAttribute<MultipleDependencyAttribute>();
                if (i == 0)
                {
                    if (multiple)
                    {
                        services.Add(descriptor);
                    }
                    else
                    {
                        AddSingleService(services, descriptor, dependencyAttribute);
                    }
                }
                else
                {
                    //有多个接口，后边的接口注册使用第一个接口的实例，保证同个实现类的多个接口获得同一实例
                    Type firstServiceType = serviceTypes[0];
                    descriptor = new ServiceDescriptor(serviceType, provider => provider.GetService(firstServiceType), lifetime.Value);
                    if (multiple)
                    {
                        services.Add(descriptor);
                    }
                    else
                    {
                        AddSingleService(services, descriptor, dependencyAttribute);
                    }
                }
            }
        }

        private static void AddSingleService(IServiceCollection services,
    ServiceDescriptor descriptor,
    [CanBeNull] DependencyAttribute dependencyAttribute)
        {
            if (dependencyAttribute?.ReplaceExisting == true)
            {
                services.Replace(descriptor);
            }
            else if (dependencyAttribute?.TryAdd == true)
            {
                services.TryAdd(descriptor);
            }
            else
            {
                services.Add(descriptor);
            }
        }
        /// <summary>
        /// 以类型实现的接口进行服务添加，需排除
        /// <see cref="IDisposable"/>等非业务接口，如无接口则注册自身
        /// </summary>
        /// <param name="services">服务映射信息集合</param>
        /// <param name="dependencyTypes">要注册的实现类型集合</param>
        /// <param name="lifetime">注册的生命周期类型</param>
        protected virtual IServiceCollection AddTypeWithInterfaces(IServiceCollection services, Type[] dependencyTypes, ServiceLifetime lifetime)
        {
            foreach (Type implementationType in dependencyTypes.Where(o => !o.IsAbstract || !o.IsInterface))
            {
                //if (implementationType.IsAbstract || implementationType.IsInterface)
                //{
                //    continue;
                //}
                Type[] interfaceTypes = GetImplementedInterfaces(implementationType);
                if (interfaceTypes.Length == 0)
                {
                    services.TryAdd(new ServiceDescriptor(implementationType, implementationType, lifetime));
                    continue;
                }
                for (int i = 0; i < interfaceTypes.Length; i++)
                {
                    Type interfaceType = interfaceTypes[i];
                    if (lifetime == ServiceLifetime.Transient)
                    {
                        services.TryAddEnumerable(new ServiceDescriptor(interfaceType, implementationType, lifetime));
                        continue;
                    }
                    bool multiple = interfaceType.HasAttribute<MultipleDependencyAttribute>();
                    if (i == 0)
                    {
                        if (multiple)
                        {
                            services.Add(new ServiceDescriptor(interfaceType, implementationType, lifetime));
                        }
                        else
                        {
                            services.TryAdd(new ServiceDescriptor(interfaceType, implementationType, lifetime));
                        }
                    }
                    else
                    {
                        //有多个接口时，后边的接口注册使用第一个接口的实例，保证同个实现类的多个接口获得同一个实例
                        Type firstInterfaceType = interfaceTypes[0];
                        if (multiple)
                        {
                            services.Add(new ServiceDescriptor(interfaceType, provider => provider.GetService(firstInterfaceType), lifetime));
                        }
                        else
                        {
                            services.TryAdd(new ServiceDescriptor(interfaceType, provider => provider.GetService(firstInterfaceType), lifetime));
                        }
                    }
                }
            }
            return services;


        }

        /// <summary>
        /// 重写以实现 从类型获取要注册的<see cref="ServiceLifetime"/>生命周期类型
        /// </summary>
        /// <param name="type">类型</param>
        /// <returns>生命周期类型</returns>
        protected virtual ServiceLifetime? GetLifetimeOrNull(Type type)
        {
            DependencyAttribute attribute = type.GetAttribute<DependencyAttribute>();
            if (attribute != null)
            {
                return attribute.Lifetime;
            }

            if (type.IsDeriveClassFrom<ITransientDependency>())
            {
                return ServiceLifetime.Transient;
            }

            if (type.IsDeriveClassFrom<IScopeDependency>())
            {
                return ServiceLifetime.Scoped;
            }

            if (type.IsDeriveClassFrom<ISingletonDependency>())
            {
                return ServiceLifetime.Singleton;
            }

            return null;
        }

        private Type[] GetImplementedInterfaces(Type type)
        {

            Type[] exceptInterfaces = { typeof(IDisposable) };
            Type[] interfaceTypes = type.GetInterfaces().Where(t => !exceptInterfaces.Contains(t) && !t.HasAttribute<IgnoreDependencyAttribute>()).ToArray();
            for (int index = 0; index < interfaceTypes.Length; index++)
            {
                Type interfaceType = interfaceTypes[index];
                if (interfaceType.IsGenericType && !interfaceType.IsGenericTypeDefinition && interfaceType.FullName == null)
                {
                    interfaceTypes[index] = interfaceType.GetGenericTypeDefinition();
                }
            }
            return interfaceTypes;
        }

    }
}
